package com.txtdhis.consumer.manage.controller;


import com.txtdhis.common.domain.User;
import com.txtdhis.common.util.Constant;
import com.txtdhis.consumer.exception.CustomException;
import com.txtdhis.consumer.exception.CustomUnauthorizedException;
import com.txtdhis.consumer.manage.service.UserService;
import com.txtdhis.consumer.po.ResponseBean;
import com.txtdhis.consumer.util.JedisUtil;
import com.txtdhis.consumer.util.JsonConvertUtil;
import com.txtdhis.consumer.util.JwtUtil;
import com.txtdhis.consumer.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/manage")
@PropertySource("classpath:config.properties")
@Slf4j
public class UserLoginController {

    /**
     * RefreshToken过期时间
     */
    @Value("${refreshTokenExpireTime}")
    private String refreshTokenExpireTime;

    @Autowired
    public UserService userservice;

    @Autowired
    private  UserUtil userUtil;

    @PostMapping("/login")
    public ResponseBean login(@RequestBody User user, HttpServletResponse httpServletResponse) {
        // 查询数据库中的帐号信息
        User userDtoTemp = new User();
        userDtoTemp.setUsername(user.getUsername());
        userDtoTemp = userservice.queryUserForList(userDtoTemp).get(0);
        if (userDtoTemp == null) {
            throw new CustomUnauthorizedException("该帐号不存在(The account does not exist.)");
        }
        // 密码进行AES解密
        //String key = userDtoTemp.getPassword();
        String key = userDtoTemp.getPassword();
        // 因为密码加密是以帐号+密码的形式进行加密的，所以解密后的对比是帐号+密码
        if (key.equals(user.getPassword())) {
            // 清除可能存在的Shiro权限信息缓存
            if (JedisUtil.exists(Constant.PREFIX_SHIRO_CACHE + user.getUsername())) {
                JedisUtil.delKey(Constant.PREFIX_SHIRO_CACHE + user.getUsername());
            }
            // 设置RefreshToken，时间戳为当前时间戳，直接设置即可(不用先删后设，会覆盖已有的RefreshToken)
            String currentTimeMillis = String.valueOf(System.currentTimeMillis());
            JedisUtil.setObject(Constant.PREFIX_SHIRO_REFRESH_TOKEN + user.getUsername(), currentTimeMillis, Integer.parseInt(refreshTokenExpireTime));
            // 从Header中Authorization返回AccessToken，时间戳为当前时间戳
            String token = JwtUtil.sign(user.getUsername(), currentTimeMillis);
            httpServletResponse.setHeader("Authorization", token);
            httpServletResponse.setHeader("Access-Control-Expose-Headers", "Authorization");
            return new ResponseBean(HttpStatus.OK.value(), "登录成功(Login Success.)", null);
        } else {
            throw new CustomUnauthorizedException("帐号或密码错误(Account or Password Error.)");
        }
    }


    /**
     * 获取在线用户(查询Redis中的RefreshToken)
     * @param
     * @return ResponseBean
     * @author
     * @date 2021/9/6 9:58
     */
    @GetMapping("/online")
    @RequiresPermissions(logical = Logical.AND, value = {"user:view"})
    public ResponseBean online() {
        List<Object> userDtos = new ArrayList<Object>();
        // 查询所有Redis键
        Set<String> keys = JedisUtil.keysS(Constant.PREFIX_SHIRO_REFRESH_TOKEN + "*");
        for (String key : keys) {
            if (JedisUtil.exists(key)) {
                // 根据:分割key，获取最后一个字符(帐号)
                String[] strArray = key.split(":");
                User userDto = new User();
                userDto.setUsername(strArray[strArray.length - 1]);
                userDto =userservice.queryUserForList(userDto).get(0);
                // 设置登录时间
                //userDto.setLoginTime(new Date(Long.parseLong(JedisUtil.getObject(key).toString())));
                userDtos.add(userDto);
            }
        }
        if (userDtos == null || userDtos.size() < 0) {
            throw new CustomException("查询失败(Query Failure)");
        }
        return new ResponseBean(HttpStatus.OK.value(), "查询成功(Query was successful)", userDtos);
    }


    @GetMapping("/article")
    public ResponseBean article() {
        Subject subject = SecurityUtils.getSubject();
        // 登录了返回true
        if (subject.isAuthenticated()) {
            return new ResponseBean(HttpStatus.OK.value(), "您已经登录了(You are already logged in)", null);
        } else {
            return new ResponseBean(HttpStatus.OK.value(), "你是游客(You are guest)", null);
        }
    }


    /**
     * 获取当前登录用户信息
     * @param
     * @return ResponseBean
     * @author
     * @date 2021/9/15 11:51
     */
    @GetMapping("/info")
    @RequiresAuthentication
    public ResponseBean info() {
        // 获取当前登录用户
        User userDto = userUtil.getUser();
        // 获取当前登录用户Id
        Integer id = userUtil.getUserId();
        // 获取当前登录用户Token
        String token = userUtil.getToken();
        // 获取当前登录用户Account
        String account = userUtil.getUsername();
        return new ResponseBean(HttpStatus.OK.value(), "您已经登录了(You are already logged in)", userDto);
    }

    @GetMapping("/cha")
    @RequiresPermissions(logical = Logical.AND, value = {"user:view"})
    public ResponseBean cha() {
        try{

            SimpleAuthorizationInfo ss = (SimpleAuthorizationInfo)JedisUtil.getObject("shiro:cache:admin");
            Set str = ss.getStringPermissions();

            String str1 = JsonConvertUtil.objectToJson(JedisUtil.getObject("shiro:cache:admin"));
            return new ResponseBean(HttpStatus.OK.value(), "您已经登录了(You are already logged in)", str1);
        }catch(Exception ce)
        {
            log.error(ce.getMessage());
            throw ce;
        }

    }


}
